package com.leo.interview;

import java.util.Collections;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.*;

/**
 * 做了一个搜索引擎，搜索引擎每次搜索前需要判断搜索关键词是否在黑名单里，黑名单每天更新一次。
 * @author xuexiaolei
 * @version 2017年11月03日
 */
public class SearchEngineBlackListCache {
    private final Set<String> blackList = new CopyOnWriteArraySet<>();//黑名单集合
    private final Set<String> todayBlackList = new ConcurrentSkipListSet<>();//当天添加的黑名单


    /******内部类单例写法 start******/
    private SearchEngineBlackListCache(){}
    private static class Holder {
        private static SearchEngineBlackListCache singleton = new SearchEngineBlackListCache();
    }
    public static SearchEngineBlackListCache getInstance(){
        return Holder.singleton;
    }
    /******内部类单例写法 end******/

    /**
     * 获取黑名单列表
     * @return
     */
    public Set<String> getBlackList() {
        return Collections.unmodifiableSet(blackList);
    }

    /**
     * 判断是否在黑名单内
     * @param name
     * @return
     */
    public boolean isBlack(String name){
        return blackList.contains(name);
    }

    /**
     * 将今天的黑名单加入到黑名单内，外部系统可以定时每天执行这个方法
     */
    public void mergeBlackList(){
        synchronized (todayBlackList){
            blackList.addAll(todayBlackList);
            todayBlackList.clear();
        }
    }

    /**
     * 加入黑名单
     * @param name
     */
    public void addBlackList(String name){
        synchronized (todayBlackList) {
            todayBlackList.add(name);
        }
    }

    /**
     * 随机生成50个线程来测试
     * @param args
     */
    public static void main(String[] args) {
        SearchEngineBlackListCache cache = SearchEngineBlackListCache.getInstance();
        final int COUNT = 50;
        CountDownLatch countDownLatch = new CountDownLatch(COUNT);
        ExecutorService exec = Executors.newFixedThreadPool(COUNT);
        for (int i = 0; i < COUNT; i++) {
            exec.execute(new Runnable() {
                @Override public void run() {
                    try {
                        countDownLatch.countDown();
                        countDownLatch.await();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    cache.addBlackList(UUID.randomUUID().toString());//随机增加黑名单字符串
                    cache.mergeBlackList();
                    System.out.println(cache.getBlackList().size());
                }
            });
        }
        exec.shutdown();
    }
}
